﻿namespace ChumChase.Model
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Windows;
    using Caliburn.MVP.Presenters;
    using Presenters;
    using Services;

    public interface IApplicationModel : IPresenterManager
    {
        void Start();
        void DisplaySettings();
    }

    public class ApplicationModel : PresenterManager, IApplicationModel
    {
        private readonly IFeedProviderCatalog _catalog;
        private readonly IScheduler _scheduler;
        private readonly ISettingsPresenter _settingsPresenter;
        private readonly Shell _shell;
        private readonly ILocalStorage _storage;
        private IUserSettings _settings;

        public ApplicationModel(Shell shell,
                                IFeedProviderCatalog catalog,
                                ISettingsPresenter settingsPresenter,
                                IScheduler scheduler,
                                IUserSettings settings,
                                ILocalStorage storage)
        {
            _shell = shell;
            _catalog = catalog;
            _settingsPresenter = settingsPresenter;
            _scheduler = scheduler;
            _settings = settings;
            _storage = storage;

            Feeds = new ObservableCollection<FeedView>();
            Feed = new FeedView();
        }

        public FeedView Feed { get; set; }
        public ObservableCollection<FeedView> Feeds { get; private set; }

        #region IApplicationModel Members

        public void Start()
        {
            foreach (IFeedProvider provider in _catalog.Providers)
            {
                MergeTemplatesFromPlugins(provider);
            }

            LoadSettings();

            _shell.DataContext = this;
            _shell.Show();

            if (_settings.FeedDefinitions.Count == 0)
            {
                PromptForSetup();
            }
            else
            {
                LoadFeeds();

                //_scheduler.Start();
                //_scheduler.OnTick += Scheduler_Tick;
            }
        }

        public void DisplaySettings()
        {
            this.Open(_settingsPresenter);
        }

        private void PromptForSetup()
        {
            this.Open(_settingsPresenter);
        }

        private void LoadFeeds()
        {
            foreach (FeedDefinition definition in _settings.FeedDefinitions)
            {
                //Feeds.Add();                
            }
        }

        #endregion

        private void Scheduler_Tick(object sender, EventArgs e)
        {
            UpdateFeed();
        }

        private void LoadSettings()
        {
            try
            {
                var loadedSettings = _storage.Load<UserSettings>(UserSettings.FileName);
                if (loadedSettings != null) _settings = loadedSettings;
            }
            catch
            {
                //TODO: log, inform?
            }

            foreach (IFeedProvider provider in _catalog.Providers)
            {
                provider.LoadSettings(_storage);
            }
        }

        public void UpdateFeed()
        {
            var master = new List<IFeedEntry>();

            foreach (IFeedProvider provider in _catalog.Providers)
            {
                GetInitialEntries(provider, master);
            }

            foreach (IFeedEntry entry in master.OrderByDescending(x => x.CreatedOn))
            {
                Feed.Entries.Add(entry);
            }
        }

        public void ClosePresenter(IPresenter presenter)
        {
            Shutdown(presenter, b => { });
            this.Open(new FeedPresenter(Feed));
        }

        private static void GetInitialEntries(IFeedProvider provider, IList<IFeedEntry> master)
        {
            IEnumerable<IFeedEntry> entries = provider.GetEntriesFor("default");

            foreach (IFeedEntry entry in entries)
            {
                master.Add(entry);
            }
        }

        private static void MergeTemplatesFromPlugins(IFeedProvider provider)
        {
            ResourceDictionary resources = Application.Current.Resources;
            foreach (DataTemplate template in provider.DataTemplates)
            {
                if (template != null && !resources.Contains(template.DataTemplateKey))
                    resources.Add(template.DataTemplateKey, template);
            }
        }
    }
}